package com.tangbuzhi.chm.adapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.tangbuzhi.chm.R;
import com.tangbuzhi.chm.helper.OnItemDragListener;
import com.tangbuzhi.chm.helper.OnItemMoveListener;
import com.tangbuzhi.chm.model.Channel;

import java.util.ArrayList;
import java.util.List;

/**
 * http://git.oschina.net/tangbuzhi
 *
 * @author Tangbuzhi
 * @version V2.0
 * @Package com.tangbuzhi.chm.adapter
 * @Description: ${TODO}
 * @date: 2017/9/11
 */
public class ChannelAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnItemMoveListener {

    public static final int TYPE_CHANNEL_HEAD = 1000;
    public static final int TYPE_CHANNEL = 1001;
    public static final int TYPE_OTHER_HEAD = 1002;
    public static final int TYPE_OTHER = 1003;

    private int COUNT_PRE_CHANNEL = 1;
    private int COUNT_PRE_OTHER = COUNT_PRE_CHANNEL + 1;

    /*动画执行时间*/
    private long anim_duration = 360L;
    /*touch点击开始时间*/
    private long startTime = 0L;
    /*touch间隔时间，用于判断是否是‘点击’*/
    private long spaceTime = 100L;
    private Handler delayHandler = new Handler();
    /*是否为编辑状态，默认为false*/
    private boolean isEditMode = false;

    public boolean isEditMode() {
        return isEditMode;
    }

    public void setEditMode(boolean editMode) {
        isEditMode = editMode;
    }

    private Context context;
    private LayoutInflater inflater;
    private ItemTouchHelper touchHelper;
    private List<Channel> channels = new ArrayList<>();
    private List<Channel> others = new ArrayList<>();

    public ChannelAdapter(Context context, ItemTouchHelper touchHelper, List<Channel> channels, List<Channel> others) {
        this.context = context;
        this.inflater = LayoutInflater.from(context);
        this.touchHelper = touchHelper;
        this.channels = channels;
        this.others = others;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return TYPE_CHANNEL_HEAD;
        } else if (position == channels.size() + 1) {
            return TYPE_OTHER_HEAD;
        } else if (position > 0 && position <= channels.size()) {
            return TYPE_CHANNEL;
        } else {
            return TYPE_OTHER;
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
        View view;
        switch (viewType) {
            case TYPE_CHANNEL_HEAD:
                view = inflater.inflate(R.layout.item_channel_header, parent, false);
                final HeadViewHolder headHolder = new HeadViewHolder(view);
                headHolder.tvEdit.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (isEditMode) {
                            headHolder.tvEdit.setText(R.string.edit);
                        } else {
                            headHolder.tvEdit.setText(R.string.finish);
                        }
                        changeEditMode((RecyclerView) parent, isEditMode);
                        isEditMode = !isEditMode;
                    }
                });
                return headHolder;
            case TYPE_CHANNEL:
                view = inflater.inflate(R.layout.item_channel, parent, false);
                final ChannelViewHolder chHolder = new ChannelViewHolder(view);
                chHolder.channel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        int position = chHolder.getAdapterPosition();
                        if (isEditMode) {
                            RecyclerView recycler = (RecyclerView) parent;
                            View targetView = recycler.getLayoutManager().findViewByPosition(channels.size() + COUNT_PRE_CHANNEL);
                            View currentView = recycler.getLayoutManager().findViewByPosition(position);
                            // 如果targetView不在屏幕内,则indexOfChild为-1  此时不需要添加动画,因为此时notifyItemMoved自带一个向目标移动的动画
                            // 如果在屏幕内,则添加一个位移动画
                            if (recycler.indexOfChild(currentView) >= 0) {
                                RecyclerView.LayoutManager manager = recycler.getLayoutManager();
                                int spanCount = ((GridLayoutManager) manager).getSpanCount();
                                int targetX, targetY;
                                // 移动后 高度将变化 (我的频道Grid 最后一个item在新的一行第一个)
                                if ((channels.size() - COUNT_PRE_CHANNEL) % spanCount == 0) {
                                    View target = recycler.getLayoutManager().findViewByPosition(channels.size() + COUNT_PRE_CHANNEL);
                                    targetX = target.getLeft();
                                    targetY = target.getTop();
                                } else {
                                    targetX = targetView.getLeft();
                                    targetY = targetView.getTop();
                                }
                                moveCh2Other(chHolder);
                                startAnim(recycler, currentView, targetX, targetY);
                            } else {
                                moveCh2Other(chHolder);
                            }
                        } else {
                            onChannelItemClickListener.channelItemClick(position - COUNT_PRE_CHANNEL, channels.get(position - COUNT_PRE_CHANNEL).getName());
                        }
                    }
                });
                chHolder.channel.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View view) {
                        if (!isEditMode) {
                            RecyclerView recycler = (RecyclerView) parent;
                            changeEditMode(recycler, isEditMode);
                            isEditMode = !isEditMode;
                            View itemView = recycler.getChildAt(0);
                            if (itemView == recycler.getLayoutManager().findViewByPosition(0)) {//双重判断itemview为channel的头布局
                                TextView text = itemView.findViewById(R.id.tv_edit);
                                text.setText(R.string.finish);
                            }
                        }
                        touchHelper.startDrag(chHolder);
                        return true;
                    }
                });
                chHolder.channel.setOnTouchListener(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View view, MotionEvent motionEvent) {
                        if (isEditMode) {
                            switch (motionEvent.getAction()) {
                                case MotionEvent.ACTION_DOWN:
                                    startTime = System.currentTimeMillis();
                                    break;
                                case MotionEvent.ACTION_MOVE:
                                    if (System.currentTimeMillis() - startTime > spaceTime) {
                                        touchHelper.startDrag(chHolder);
                                    }
                                    break;
                                case MotionEvent.ACTION_CANCEL:
                                case MotionEvent.ACTION_UP:
                                    startTime = 0;
                                    break;
                                default:
                                    break;
                            }
                        }
                        return false;
                    }
                });
                return chHolder;
            case TYPE_OTHER_HEAD:
                view = inflater.inflate(R.layout.item_other_header, parent, false);
                return new RecyclerView.ViewHolder(view) {
                };
            case TYPE_OTHER:
                view = inflater.inflate(R.layout.item_channel, parent, false);
                final OtherViewHolder otherHolder = new OtherViewHolder(view);
                otherHolder.channel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        RecyclerView recycler = (RecyclerView) parent;
                        RecyclerView.LayoutManager manager = recycler.getLayoutManager();
                        int currentPosition = otherHolder.getAdapterPosition();
                        View currentView = manager.findViewByPosition(currentPosition);
                        View previousView = manager.findViewByPosition(channels.size());
                        // 如果targetView不在屏幕内,则为-1  此时不需要添加动画,因为此时notifyItemMoved自带一个向目标移动的动画
                        // 如果在屏幕内,则添加一个位移动画
                        if (recycler.indexOfChild(previousView) >= 0) {
                            int targetX = previousView.getLeft();
                            int targetY = previousView.getTop();
                            int targetPosition = channels.size() - COUNT_PRE_CHANNEL + COUNT_PRE_OTHER;
                            int spanCount = ((GridLayoutManager) manager).getSpanCount();
                            // target 在最后一行第一个
                            if ((targetPosition - COUNT_PRE_CHANNEL) % spanCount == 0) {
                                View targetView = manager.findViewByPosition(targetPosition);
                                targetX = targetView.getLeft();
                                targetY = targetView.getTop();
                            } else {
                                targetX += previousView.getWidth();
                                if (((GridLayoutManager) manager).findLastVisibleItemPosition() == getItemCount() - 1) {
                                    // 最后的item在最后一行第一个位置
                                    if ((getItemCount() - 1 - channels.size() - COUNT_PRE_OTHER) % spanCount == 0) {
                                        // RecyclerView实际高度 > 屏幕高度 && RecyclerView实际高度 < 屏幕高度 + item.height
                                        int firstVisibleItemPosition = ((GridLayoutManager) manager).findFirstVisibleItemPosition();
                                        if (firstVisibleItemPosition == 0) {
                                            // FirstCompletelyVisibleItemPosition == 0 即 内容不满一屏幕 , targetY值不需要变化
                                            // // FirstCompletelyVisibleItemPosition != 0 即 内容满一屏幕 并且 可滑动 , targetY值 + firstItem.getTop
                                            if (((GridLayoutManager) manager).findFirstCompletelyVisibleItemPosition() != 0) {
                                                int offset = (-recycler.getChildAt(0).getTop()) - recycler.getPaddingTop();
                                                targetY += offset;
                                            }
                                        } else { // 在这种情况下 并且 RecyclerView高度变化时(即可见第一个item的 position != 0),
                                            // 移动后, targetY值  + 一个item的高度
                                            targetY += previousView.getHeight();
                                        }
                                    }
                                }
                            }
                            // 如果当前位置是otherChannel可见的最后一个
                            // 并且 当前位置不在grid的第一个位置
                            // 并且 目标位置不在grid的第一个位置
                            // 则 需要延迟250秒 notifyItemMove , 这是因为这种情况 , 并不触发ItemAnimator , 会直接刷新界面
                            // 导致我们的位移动画刚开始,就已经notify完毕,引起不同步问题
                            if (currentPosition == ((GridLayoutManager) manager).findLastVisibleItemPosition()
                                    && (currentPosition - channels.size() - COUNT_PRE_OTHER) % spanCount != 0
                                    && (targetPosition - COUNT_PRE_CHANNEL) % spanCount != 0) {
                                moveOtherToMyWithDelay(otherHolder);
                            } else {
                                moveOther2Ch(otherHolder);
                            }
                            startAnim(recycler, currentView, targetX, targetY);
                        } else {
                            moveOther2Ch(otherHolder);
                        }
                    }
                });
                return otherHolder;
            default:
                return null;
        }
    }

    private void moveOther2Ch(OtherViewHolder otherHolder) {
        int position = processItemRemoveAdd(otherHolder);
        if (position == -1) {
            return;
        }
        notifyItemMoved(position, channels.size());
    }

    private void moveOtherToMyWithDelay(OtherViewHolder otherHolder) {
        final int position = processItemRemoveAdd(otherHolder);
        if (position == -1) {
            return;
        }
        delayHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                notifyItemMoved(position, channels.size() - 1 + COUNT_PRE_CHANNEL);
            }
        }, anim_duration);
    }

    private int processItemRemoveAdd(OtherViewHolder otherHolder) {
        int position = otherHolder.getAdapterPosition();

        int startPosition = position - channels.size() - COUNT_PRE_OTHER;
        if (startPosition > others.size() - 1) {
            return -1;
        }
        Channel item = others.get(startPosition);
        others.remove(startPosition);
        channels.add(item);
        return position;
    }

    private void changeEditMode(RecyclerView parent, boolean isEditMode) {
        for (int i = 0; i < parent.getChildCount(); i++) {
            View view = parent.getChildAt(i);
            View edit = view.findViewById(R.id.edit);
            if (edit != null) {
                edit.setVisibility(isEditMode ? View.GONE : View.VISIBLE);
            }
        }
    }

    /*channel => other*/
    private void moveCh2Other(ChannelViewHolder chHolder) {
        int position = chHolder.getAdapterPosition();
        int startPosition = position - COUNT_PRE_CHANNEL;
        if (startPosition > channels.size() - COUNT_PRE_CHANNEL) {
            return;
        }
        Channel channel = channels.get(startPosition);
        channels.remove(startPosition);
        others.add(0, channel);
        notifyItemMoved(position, channels.size() + COUNT_PRE_OTHER);
    }

    private void startAnim(RecyclerView recycler, final View currentView, int targetX, int targetY) {
        final ViewGroup parent = (ViewGroup) recycler.getParent();
        final ImageView mirrorView = getMirrorView(parent, recycler, currentView);
        TranslateAnimation animation = getTranslateAnimation(targetX - currentView.getLeft(), targetY - currentView.getTop());
        currentView.setVisibility(View.GONE);
        mirrorView.startAnimation(animation);
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                parent.removeView(mirrorView);
                if (currentView.getVisibility() == View.GONE) {
                    currentView.setVisibility(View.VISIBLE);
                }
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
    }

    /*获取要移动的view的镜像view*/
    private ImageView getMirrorView(ViewGroup parent, RecyclerView recycler, View view) {
        /**
         * 我们要获取cache首先要通过setDrawingCacheEnable方法开启cache，然后再调用getDrawingCache方法就可以获得view的cache图片了。
         buildDrawingCache方法可以不用调用，因为调用getDrawingCache方法时，若果cache没有建立，系统会自动调用buildDrawingCache方法生成cache。
         若想更新cache, 必须要调用destoryDrawingCache方法把旧的cache销毁，才能建立新的。
         当调用setDrawingCacheEnabled方法设置为false, 系统也会自动把原来的cache销毁。
         */
        view.destroyDrawingCache();
        view.setDrawingCacheEnabled(true);
        ImageView mirrorView = new ImageView(context);
        Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
        mirrorView.setImageBitmap(bitmap);

        view.setDrawingCacheEnabled(false);
        int[] locations = new int[2];
        view.getLocationOnScreen(locations);
        int[] parentLocations = new int[2];
        recycler.getLocationOnScreen(parentLocations);

        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(bitmap.getWidth(), bitmap.getHeight());
        params.setMargins(locations[0], locations[1] - parentLocations[1], 0, 0);
        parent.addView(mirrorView, params);
        return mirrorView;
    }

    private TranslateAnimation getTranslateAnimation(int left, int top) {
        TranslateAnimation animation = new TranslateAnimation(
                Animation.RELATIVE_TO_SELF, 0f,
                Animation.ABSOLUTE, left,
                Animation.RELATIVE_TO_SELF, 0f,
                Animation.ABSOLUTE, top
        );
        //RecyclerView默认移动动画250ms 这里设置360ms 是为了防止在位移动画结束后 remove(view)过早 导致闪烁
        animation.setDuration(anim_duration);
        animation.setFillAfter(true);
        return animation;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof HeadViewHolder) {
            HeadViewHolder headHolder = (HeadViewHolder) holder;
            if (isEditMode) {
                headHolder.tvEdit.setText(R.string.finish);
            } else {
                headHolder.tvEdit.setText(R.string.edit);
            }
        }
        if (holder instanceof ChannelViewHolder) {
            ChannelViewHolder chHolder = (ChannelViewHolder) holder;
            chHolder.channel.setText(channels.get(position - COUNT_PRE_CHANNEL).getName());
            chHolder.edit.setVisibility(isEditMode ? View.VISIBLE : View.GONE);
        }
        if (holder instanceof OtherViewHolder) {
            OtherViewHolder otherHolder = (OtherViewHolder) holder;
            otherHolder.channel.setText(others.get(position - channels.size() - COUNT_PRE_OTHER).getName());
            otherHolder.edit.setVisibility(isEditMode ? View.VISIBLE : View.GONE);
            //otherHolder.edit.setVisibility(View.GONE);
        }
    }

    @Override
    public int getItemCount() {
        return channels.size() + others.size() + COUNT_PRE_OTHER;
    }

    private OnChannelItemClickListener onChannelItemClickListener;

    public void setOnChannelItemClickListener(OnChannelItemClickListener onChannelItemClickListener) {
        this.onChannelItemClickListener = onChannelItemClickListener;
    }

    @Override
    public void onItemMove(int fromPosition, int toPosition) {
        Channel channel = channels.get(fromPosition - COUNT_PRE_CHANNEL);
        channels.remove(fromPosition - COUNT_PRE_CHANNEL);
        channels.add(toPosition - COUNT_PRE_CHANNEL, channel);
        notifyItemMoved(fromPosition, toPosition);
    }

    public interface OnChannelItemClickListener {
        void channelItemClick(int position, String name);
    }

    private class ChannelViewHolder extends RecyclerView.ViewHolder implements OnItemDragListener {
        private TextView channel;
        private ImageView edit;

        public ChannelViewHolder(View itemView) {
            super(itemView);
            channel = (TextView) itemView.findViewById(R.id.channel);
            edit = (ImageView) itemView.findViewById(R.id.edit);
        }

        @Override
        public void onItemDragStart() {
            channel.setBackgroundResource(R.drawable.bg_channel_p);
        }

        @Override
        public void onItemDragFinish() {
            channel.setBackgroundResource(R.drawable.bg_channel);
        }
    }

    private class OtherViewHolder extends RecyclerView.ViewHolder {
        private TextView channel;
        private ImageView edit;

        public OtherViewHolder(View itemView) {
            super(itemView);
            channel = (TextView) itemView.findViewById(R.id.channel);
            edit = (ImageView) itemView.findViewById(R.id.edit);
        }
    }

    private class HeadViewHolder extends RecyclerView.ViewHolder {
        private TextView tvEdit;

        public HeadViewHolder(View itemView) {
            super(itemView);
            tvEdit = (TextView) itemView.findViewById(R.id.tv_edit);
        }
    }

    public List<String> getChannels() {
        List<String> lists = new ArrayList<>();
        for (int i = 0; i < channels.size(); i++) {
            lists.add(channels.get(i).getName());
        }
        if (lists.size() > 0) {
            return lists;
        } else {
            lists.add("nothing");
        }
        return lists;
    }
}
